/*
 * AutoAnswer
 * Copyright (C) 2010 EverySoft
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * This file incorporates work covered by the following copyright and
 * permission notice:
 *
 *   Copyright (C) 2010 Tedd Scofield
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 */

package com.voicesys;

import java.lang.reflect.Method;
import java.util.Calendar;

import com.android.internal.telephony.ITelephony;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Binder;
import android.os.Environment;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;

public class AutoAnswerIntentService extends IntentService {
	private final IBinder mBinder = new LocalBinder();

	// public boolean isFinished = true;
	//
	// public boolean isFinished() {
	// return isFinished;
	// }
	//
	// public void setFinished(boolean isFinished) {
	// this.isFinished = isFinished;
	// }

	public AutoAnswerIntentService() {
		super("AutoAnswerIntentService");
	}

	public class LocalBinder extends Binder {
		AutoAnswerIntentService getService() {
			return AutoAnswerIntentService.this;
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

	@Override
	protected void onHandleIntent(Intent intent) {
		context = getBaseContext();
		// Load preferences
		int events = PhoneStateListener.LISTEN_CALL_STATE;
		tm.listen(phoneStateListener, events);
	}

	@Override
	public void onCreate() {
		super.onCreate();
		context = getBaseContext();
		// Load preferences
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
		tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
	}

	private final PhoneStateListener phoneStateListener = new PhoneStateListener() {
		private Context context;

		@Override
		public void onCallStateChanged(int state, String incomingNumber) {
			// if (!isFinished) {
			switch (state) {

			case TelephonyManager.CALL_STATE_RINGING:

				incnum = incomingNumber;
				// Answer the phone
				// answerPhoneCall();

				break;
			case TelephonyManager.CALL_STATE_OFFHOOK:
				context = getBaseContext();
				AudioManager audioManager = getAudioManager(context);
				audioManager.setSpeakerphoneOn(true);
				audioManager.setMode(AudioManager.MODE_IN_CALL);

				// UnMute the call
				audioManager.setMicrophoneMute(false);

				// playGreetingAudio();
				// playBeepAudio();

				// startRecording(tm);

				break;
			case TelephonyManager.CALL_STATE_IDLE:
				stopRecording();
			}

			// }
			super.onCallStateChanged(state, incomingNumber);
		}

	};

	public void answerPhoneCall() {
		try {
			answerPhoneAidl();
		} catch (Exception e) {
			e.printStackTrace();
			answerPhoneHeadsethook();
		}
		sleep(2000);
	}

	public AudioManager getAudioManager(Context context) {
		AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
		int streamMaxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
		int streamMaxVolume2 = audioManager.getStreamMaxVolume(AudioManager.MODE_IN_CALL);
		int streamMaxVolume3 = audioManager.getStreamMaxVolume(AudioManager.STREAM_DTMF);
		int streamMaxVolume4 = audioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL);
		audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, streamMaxVolume,
				AudioManager.FLAG_PLAY_SOUND);
		audioManager.setStreamVolume(AudioManager.MODE_IN_CALL, streamMaxVolume2,
				AudioManager.FLAG_PLAY_SOUND);
		audioManager.setStreamVolume(AudioManager.STREAM_DTMF, streamMaxVolume3,
				AudioManager.FLAG_PLAY_SOUND);
		audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, streamMaxVolume4,
				AudioManager.FLAG_PLAY_SOUND);
		for (int i = 0; i < 10; i++) {
			audioManager.adjustVolume(AudioManager.ADJUST_RAISE, AudioManager.FLAG_PLAY_SOUND);
		}
		return audioManager;
	}

	private void sleep(int time) {
		try {
			Thread.sleep(time);
		} catch (InterruptedException e) {
			// We don't really care
		}
	}

	private void playGreetingAudio() {
		// getAudioManager(context);
		mediaPlayer = MediaPlayer.create(context, R.raw.greeting_audio_file);
		mediaPlayer.setVolume(1, 1);
		mediaPlayer.start();
		mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
			@Override
			public void onCompletion(MediaPlayer arg0) {
				mediaPlayer.stop();
				mediaPlayer.reset();
				mediaPlayer.release();
				mediaPlayer = null;
			}
		});

	}

	public void playBeepAudio() {
		getAudioManager(context);
		mediaPlayer = MediaPlayer.create(context, R.raw.beep);
		mediaPlayer.setVolume(1, 1);
		mediaPlayer.start();
		mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
			@Override
			public void onCompletion(MediaPlayer arg0) {
				mediaPlayer.stop();
				mediaPlayer.reset();
				mediaPlayer.release();
				mediaPlayer = null;
			}
		});
	}

	public void startRecording(TelephonyManager tm) {
		int state = tm.getCallState();

		Calendar calendar = Calendar.getInstance();

		int day = calendar.get(Calendar.DATE), mont = calendar.get(Calendar.MONTH), yea = calendar
				.get(Calendar.YEAR), hou = calendar.get(Calendar.HOUR_OF_DAY), min = calendar
				.get(Calendar.MINUTE);
		String audioFile = "" + day + "_" + mont + "_" + yea + "_" + hou + "_" + min + "_" + incnum
				+ ".3gp";
		if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
			String mFileName = Environment.getExternalStorageDirectory().getAbsolutePath() + "/"
					+ audioFile;
			recorderInstance = Recorder.getRecorderInstance(this);
			th = new Thread(recorderInstance);
			recorderInstance.setFileName(mFileName);
			th.start();
			recorderInstance.setRecording(true);
		}

	}

	public void stopRecording() {
		recorderInstance.setRecording(false);

		try {
			th.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@Override
	public boolean stopService(Intent name) {
		// isFinished = true;
		// TODO Auto-generated method stub
		tm.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
		return super.stopService(name);
	}

	// @Override
	// public boolean stopService(Intent name) {
	// stopRecording();
	// try {
	// callReject(getBaseContext());
	// } catch (Exception e) {
	// System.out.println("Exception:" + e.getMessage());
	// e.printStackTrace();
	// }
	// return super.stopService(name);
	// };

	private String incnum;
	private TelephonyManager tm;
	private Recorder recorderInstance;
	private Thread th;
	private MediaPlayer mediaPlayer;
	private Context context;

	private void answerPhoneHeadsethook() {
		// Simulate a press of the headset button to pick up the call
		Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);
		buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
				KeyEvent.KEYCODE_HEADSETHOOK));
		context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED");

		// froyo and beyond trigger on buttonUp instead of buttonDown
		Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
		buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
				KeyEvent.KEYCODE_HEADSETHOOK));
		context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");
	}

	public void endPhoneCall() {
		Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);
		buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
				KeyEvent.KEYCODE_ENDCALL));
		context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED");
		// froyo and beyond trigger on buttonUp instead of buttonDown
		Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
		buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
				KeyEvent.KEYCODE_ENDCALL));
		context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");
	}

	@SuppressWarnings("unchecked")
	private void answerPhoneAidl() throws Exception {
		// Set up communication with the telephony service (thanks to Tedd's
		// Droid Tools!)
		TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
		Class c = Class.forName(tm.getClass().getName());
		Method m = c.getDeclaredMethod("getITelephony");
		m.setAccessible(true);
		ITelephony telephonyService;
		telephonyService = (ITelephony) m.invoke(tm);

		// Silence the ringer and answer the call!
		telephonyService.silenceRinger();
		telephonyService.answerRingingCall();
	}

	public void callReject() throws Exception {
		try {
			TelephonyManager manager = (TelephonyManager) context
					.getSystemService(Context.TELEPHONY_SERVICE);
			Class c = Class.forName(manager.getClass().getName());
			Method m = c.getDeclaredMethod("getITelephony");
			m.setAccessible(true);
			ITelephony telephony = (ITelephony) m.invoke(manager);
			telephony.endCall();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
